subdiagnosis <- readr::read_tsv(
file.path("..", "..", "..", "data", "current", params$scpca_project_id, "single_cell_metadata.tsv"),
show_col_types = FALSE
) |>
dplyr::filter(scpca_sample_id == params$sample_id) |>
dplyr::pull(subdiagnosis)The aim is to explore the clustering and label transfers for the sample SCPCS000172. This sample has a(n) Favorable subdiagnosis.
In order to explore the clustering results, we look into some marker genes, pathways enrichment and label transfer.
This approach would provide us a rapid idea of the quality of the clustering:
# The base path for the OpenScPCA repository, found by its (hidden) .git directory
repository_base <- rprojroot::find_root(rprojroot::is_git_root)
# The current data directory, found within the repository base directory
data_dir <- file.path(repository_base, "data", "current", params$scpca_project_id)
# The path to this module
module_base <- file.path(repository_base, "analyses", "cell-type-wilms-tumor-06")In this notebook, we are working with the Wilms tumor sample defined
in SCPCS000172 from the Wilms tumor dataset SCPCP000006. We work with
the pre-processed and labeled Seurat object that is the
output of
02b_label-transfer_fetal_kidney_reference_Stewart.Rmd saved
in the results directory.
To explore the clustering results, we look into some marker genes reported here:
Reports will be saved in the notebook directory. The
pre-processed and annotated Seurat object per samples are
saved in the result folder.
Here we defined function that will be used multiple time all along the notebook.
For a Seurat object objectand a metadata
metadata, the function visualize_metadata will
plot FeaturePlot and BarPlot
object is the Seurat object
metadata the gene or quantitative value to be
plotted
group.by is the metadata used for grouping the
violin plots
visualize_metadata <- function(object, meta, group.by){
if(is.numeric(object@meta.data[,meta])){
d <- SCpubr::do_FeaturePlot(object,
features = meta,
pt.size = 0.2,
legend.width = 0.5,
legend.length = 5,
legend.position = "right") + ggtitle(meta)
b <- SCpubr::do_ViolinPlot(srat,
features = meta,
ncol = 1,
group.by = group.by,
legend.position = "none")
return(d + b + plot_layout(ncol = 2, widths = c(2,4)))
}
else{
d <- SCpubr::do_DimPlot(object, reduction="umap", group.by = group.by, label = TRUE, repel = TRUE) + ggtitle(paste0(meta," - umap")) + theme(text=element_text(size=18))
b <- SCpubr::do_BarPlot(sample = object,
group.by = meta,
split.by = group.by,
position = "fill",
font.size = 10,
legend.ncol = 3) +
ggtitle("% cells")+
xlab(print(group.by)) +
theme(text=element_text(size=18))
return(d + b + plot_layout(ncol = 2, widths = c(2,4)))
}
}For a Seurat object objectand a features
features, the function visualize_feature will
plot FeaturePlot and ViolinPlot
object is the Seurat object
features the gene or quantitative value to be
plotted
group.by is the metadata used for grouping the
violin plots
visualize_feature <- function(object, features, group.by = "seurat_clusters"){
feature_symbol <- AnnotationDbi::select(org.Hs.eg.db,
keys=features,
columns="SYMBOL",
keytype="ENSEMBL")
d <- SCpubr::do_FeaturePlot(object,
features = feature_symbol$ENSEMBL,
pt.size = 0.2,
legend.width = 0.5,
legend.length = 5,
legend.position = "right") + ggtitle(feature_symbol$SYMBOL)
b <- SCpubr::do_ViolinPlot(srat,
features = feature_symbol$ENSEMBL,
ncol = 1,
group.by = group.by,
legend.position = "none",
assay = "SCT") + ylab(feature_symbol$SYMBOL)
return(d + b + plot_layout(ncol = 2, widths = c(2,4)))
}ModuleScore from a MSigDB
datasetFor a Seurat object object, the function
MSigDB_score will calculate a score using
AddModuleScore() function for a MSigDB gene set
gs_name in the category category
object is the Seurat object to calculate the score.
Score will be added in the metadata of this object.
category is a MSigDB collection (https://www.gsea-msigdb.org/gsea/msigdb/collections.jsp).
values in
c("H", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8")
gs_name is the name of a MSigDB gene set,
e.g. "HALLMARK_P53_PATHWAY"
name is the name of the module
MSigDB_score <- function(object, category, gs_name, name){
set <- msigdbr(species = "human", category = category)
set_list <- set %>%
dplyr::filter(gs_name == gs_name) %>%
dplyr::distinct(gs_name, gene_symbol, human_ensembl_gene) %>% as.data.frame()
set_list <- list(set_list$human_ensembl_gene)
suppressWarnings({
object <- AddModuleScore(object, features = set_list, name = name)
})
return(object)
}Enrichment_plotaim to perform enrichment of the marker
genes for each of the Seurat clusters and summarize the results in a
dotplot.
category is the MSigDB category or collection to be
used values in
c("H", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8")
signatures is a list of marker genes per
cluster
backgroundis the universe used for
enrichment
Enrichment_plot <- function(category, signatures, background){
## define genesets
tryCatch( expr = {
gene_set <- msigdbr(species = "human", category = category)
msigdbr_set <- gene_set %>% dplyr::distinct(gs_name, ensembl_gene) %>% as.data.frame()
cclust<-compareCluster(geneCluster = signatures,
fun = enricher,
TERM2GENE = msigdbr_set,
universe=background)
d <- dotplot(cclust,showCategory=15) + scale_y_discrete(labels=function(x) str_wrap(x, width=40))
return(d)
},
error = function(e) { print("No enrichment") } )
}do_Table_Heatmap shows heatmap of counts of cells for
combinations of two metadata variables
data seurat objectfirst_group is the name of the first metadata to group
the cellslast_group is the name of the second metadata to group
the cellsdo_Table_Heatmap <- function(data, first_group, last_group ){
df <- data@meta.data %>%
mutate_if(sapply(data@meta.data, is.character), as.factor) %>%
group_by( !!sym(first_group), !!sym(last_group))%>%
summarise(Nb = log(n()))
p <- ggplot(df, aes(x= !!sym(first_group), y = !!sym(last_group), fill = Nb)) +
geom_tile() +
scale_fill_viridis_c() +
theme_bw() +
theme(text = element_text(size = 20)) +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
guides(fill=guide_legend(title=" Number of \n cells (log)"))
return(p)
}Seurat objectWe expect up to 5 set of clusters:
d2 <- SCpubr::do_DimPlot(srat, reduction="umap", group.by = "seurat_clusters", label = TRUE) + ggtitle("Seurat Cluster - umap")
d1 <- SCpubr::do_DimPlot(srat, reduction="pca", group.by = "seurat_clusters", label = TRUE) + ggtitle("Seurat Cluster - pca")
v1 <- SCpubr::do_ViolinPlot(srat, features = c( "subsets_mito_percent"), ncol = 1, group.by = "seurat_clusters", legend.position = "none")
v2 <- SCpubr::do_ViolinPlot(srat, features = c( "detected"), ncol = 1, group.by = "seurat_clusters", legend.position = "none")
v3 <- SCpubr::do_ViolinPlot(srat, features = c( "sum"), ncol = 1, group.by = "seurat_clusters", legend.position = "none")
d1 + d2 + (v1 + v2 +v3 + plot_layout(ncol=1) ) + plot_layout(ncol = 3, widths = c(2,2,4))s.genes <- srat@assays$RNA@meta.data$gene_ids[srat@assays$RNA@meta.data$gene_symbol %in% cc.genes$s.genes]
g2m.genes <- srat@assays$RNA@meta.data$gene_ids[srat@assays$RNA@meta.data$gene_symbol %in% cc.genes$g2m.genes]
srat <- CellCycleScoring(srat, s.features = s.genes, g2m.features = g2m.genes, set.ident = FALSE)## [1] "seurat_clusters"
Here, we open the table of marker genes marker-sets/CellType_metadata.csv. Note: we do not expect to have a clear and nice pattern of expression for all of the following markers in every tumor. This is just ti get a few idea.
for(feature in CellType_metadata$ENSEMBL_ID[CellType_metadata$ENSEMBL_ID %in% rownames(srat@assays$SCT)]){
print(visualize_feature(srat, features = feature, group.by = "seurat_clusters"))
}here we will calculate a TP53 score using AddModuleScore
and the genes of the HALLMARK_P53_PATHWAY gene set.
srat <- MSigDB_score(object = srat , category = "H", gs_name = "HALLMARK_P53_PATHWAY", name = "TP53_score")
visualize_metadata(srat, meta = "TP53_score1", group.by = "seurat_clusters" )here we will calculate a DNA_repair score using
AddModuleScore and the genes of the HALLMARK_DNA_REPAIR
gene set.
srat <- MSigDB_score(object = srat , category = "H", gs_name = "HALLMARK_DNA_REPAIR", name = "DNA_repair_score")
visualize_metadata(srat, meta = "DNA_repair_score1", group.by = "seurat_clusters" )Note: Chemo-treated samples should have higher DNA-damage scores.
In addition to the list of known marker genes, we used an unbiased approach to find transcripts that characterized the different clusters.
We run DElegate::FindAllMarkers2 to find markers of the different clusters and manually check if they do make sense. DElegate::FindAllMarkers2 is an improved version of Seurat::FindAllMarkers based on pseudobulk differential expression method. Please check the preprint from Chistoph Hafemeister: https://www.biorxiv.org/content/10.1101/2023.03.28.534443v1 and tool described here: https://github.com/cancerbits/DElegate
Of note, we won’t use it for annotation, this is just here to get an idea!
feature_conversion <- srat@assays$RNA@meta.data
de_results <- DElegate::FindAllMarkers2(srat, group_column = "seurat_clusters")
#filter the most relevant markers
s.markers <- de_results[de_results$padj < params$padj_thershold & de_results$log_fc > params$lfc_threshold & de_results$rate1 > params$rate1_threshold,]
# add gene symbol for easiest interpretation of the result
s.markers$gene_ids <- s.markers$feature
s.markers <- left_join(s.markers,feature_conversion, by = c( "gene_ids") )
stopifnot(
"Error joining gene ids and feature names" = identical(s.markers$feature, s.markers$gene_ids)
)DT::datatable(s.markers, caption = ("marker genes"),
extensions = 'Buttons',
options = list( dom = 'Bfrtip',
buttons = c( 'csv', 'excel')))# Select top 5 genes for heatmap plotting
s.markers <- na.omit(s.markers)
s.markers %>%
group_by(group1) %>%
top_n(n = 5, wt = log_fc) -> top5
# subset for plotting
cells <- WhichCells(srat, downsample = 100)
ss <- subset(srat, cells = cells)
ss <- ScaleData(ss, features = top5$feature)
p1 <- SCpubr::do_DimPlot(srat, reduction="umap", group.by = "seurat_clusters", label = TRUE, repel = TRUE) + ggtitle("Seurat Cluster - umap")
p2 <- DoHeatmap(ss, features = top5$feature, cells = cells, group.by = "seurat_clusters") + NoLegend() +
scale_fill_gradientn(colors = c("#01665e","#35978f",'darkslategray3', "#f7f7f7", "#fee391","#fec44f","#F9AD03"))
p3 <- ggplot(srat@meta.data, aes(seurat_clusters, fill = seurat_clusters)) + geom_bar() + NoLegend()
common_title <- sprintf("Unsupervised clustering %s, %d cells", srat@meta.data$orig.ident[1], ncol(srat))
show((((p1 / p3) + plot_layout(heights = c(3,2)) | p2) ) + plot_layout(widths = c(1, 2)) + plot_layout(heights = c(3,1)) + plot_annotation(title = common_title))Here we perform enrichment analysis of the marker genes found in the previous section for each Seurat cluster.
We defined as universe/background all the genes expressed in the dataset, meaning the rownames of the Seurat object.
We used three gene sets from MSiGDB:
We used enricher function from clusterProfiler to perform enrichment analysis.
# define background genes = universe for enrichment
background <- rownames(srat)
# Define gene signature per cluster
signatures <- list()
for( i in unique(s.markers$group1)){
signatures[[paste0("cluster ",i)]] <- s.markers$feature[s.markers$group1 == i]
}EMT signature should be enriched in stroma cluster. E2F/proliferation should be enriched in blastema cluster. MYC(N), TP53 must be enriched in blastema cluster.
The MSigDB C8 gene set is quite relevant for kidney and nephroblastoma annotations. Epithelial (cancer and normal) cells should be enriched in mature/adulte kidney pathways while blastema cancer cells will show enrichment of fetal kidney development pathway / cap mesenchyme.
Here, we quickly checked annotations that are present in the _processed rds object. However, the automated annotation have not been performed using a cancer specific reference or a kidney reference. We do not expect a nice labelling of the cells as the overlap of cell types between the reference and the query dataset is poor. This support the need to do a proper label transfer from the fetal kidney atlas, which is imho the best reference that can be applied to a Wilms tumor query.
## [1] "seurat_clusters"
## [1] "seurat_clusters"
## [1] "seurat_clusters"
## [1] "seurat_clusters"
## [1] "seurat_clusters"
## [1] "seurat_clusters"
## [1] "seurat_clusters"
Here we evaluate with marker genes the identification of endothelial, immune cells and other cancer and non-cancerous sub-populations.
markers = list("malignant" = CellType_metadata$ENSEMBL_ID[which(CellType_metadata$cell_class == "malignant")],
"immune"= CellType_metadata$ENSEMBL_ID[which(CellType_metadata$cell_class == "immune")],
"endothelium"= CellType_metadata$ENSEMBL_ID[which(CellType_metadata$cell_class == "endothelium")],
"non-malignant"= CellType_metadata$ENSEMBL_ID[which(CellType_metadata$cell_class == "non-malignant")])
p1 <- SCpubr::do_DotPlot(sample = srat,
group.by = "fetal_kidney_predicted.compartment",
features = markers,
axis.text.x.angle = 90,
flip = TRUE,
plot.title = "fetal_kidney_predicted.compartment"
)
p2 <- SCpubr::do_DotPlot(sample = srat,
group.by = "fetal_kidney_predicted.cell_type",
features = markers,
axis.text.x.angle = 90,
flip = TRUE,
plot.title = "fetal_kidney_predicted.cell_type"
)
p3 <- SCpubr::do_DotPlot(sample = srat,
group.by = "fetal_full_predicted.annotation.l1",
features = markers,
axis.text.x.angle = 90,
flip = TRUE,
plot.title = "fetal_full_predicted.annotation.l1"
)
p4 <- SCpubr::do_DotPlot(sample = srat,
group.by = "fetal_full_predicted.annotation.l2",
features = markers,
axis.text.x.angle = 90,
flip = TRUE,
plot.title = "fetal_full_predicted.annotation.l2"
)
p5 <- SCpubr::do_DotPlot(sample = srat,
group.by = "seurat_clusters",
features = markers,
axis.text.x.angle = 90,
flip = TRUE,
plot.title = "seurat_clusters"
)
p6 <- SCpubr::do_DotPlot(sample = srat,
group.by = "cellassign_celltype_annotation",
features = markers,
axis.text.x.angle = 90,
flip = TRUE,
plot.title = "cellassign_celltype_annotation"
)
(p1|p2)/(p3|p4) /(p5|p6)Seurat clustersHere we check wether one (or more) Seurat cluster do
correspond to one label. This would allow us to be more confident in the
annotation of immune or endothelial cells for example.
p1 <- do_Table_Heatmap( srat,
last_group = "fetal_kidney_predicted.compartment",
first_group = "seurat_clusters"
)
p2 <- do_Table_Heatmap( srat,
last_group = "fetal_full_predicted.annotation.l1",
first_group = "seurat_clusters"
)
p3 <- do_Table_Heatmap( srat,
last_group = "singler_celltype_annotation",
first_group = "seurat_clusters"
)
p4 <- do_Table_Heatmap( srat,
last_group = "cellassign_celltype_annotation",
first_group = "seurat_clusters"
)
(p1|p2)/(p3|p4)The use of the right reference is crucial for label transfer and annotation. It is recommended that the cell types in the reference is representative to the cell types to be annotated in the query.
Wilms tumors can contain up to three histologies that resemble fetal kidney: blastema, stroma, and epithelia [1, 2]. Because of their histological similarity to fetal kidneys, Wilms tumors are thought to arise from developmental derangements in embryonic renal progenitors.
In the previous step of the analysis, we selected two fetal references containing kidney samples and transfer the labels.
Here we aim to understand the overlap and differences between the two references.
Stewart et al. created a human fetal kidney atlas [3].
This reference contains only fetal kidney cells and has been precisely annotated by kidney experts.
Azimuth also provides a human fetal atlas as a reference
[4].
The data can be found on Zenodo.
The reference contain cells from 15 organs including kidney from fetal samples.
We were first nicely surprised that most of the cells in the Wilms
tumor dataset mapped to “kidney” organ (see previous report
02a_fetal_all_reference_Cao_{sample_id}.html).
# record the versions of the packages used in this analysis and other environment information
sessionInfo()## R version 4.4.1 (2024-06-14)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 22.04.4 LTS
##
## Matrix products: default
## BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
## LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.20.so; LAPACK version 3.10.0
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8 LC_MONETARY=en_US.UTF-8
## [6] LC_MESSAGES=en_US.UTF-8 LC_PAPER=en_US.UTF-8 LC_NAME=C LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## time zone: Europe/Vienna
## tzcode source: system (glibc)
##
## attached base packages:
## [1] stats4 stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] ggalluvial_0.12.5 org.Hs.eg.db_3.19.1 AnnotationDbi_1.66.0 clusterProfiler_4.12.6 enrichplot_1.24.4
## [6] msigdbr_7.5.1 sctransform_0.4.1 SeuratData_0.2.2.9001 SingleCellExperiment_1.26.0 SummarizedExperiment_1.34.0
## [11] Biobase_2.64.0 GenomicRanges_1.56.1 GenomeInfoDb_1.40.1 IRanges_2.38.1 S4Vectors_0.42.1
## [16] BiocGenerics_0.50.0 MatrixGenerics_1.16.0 matrixStats_1.3.0 patchwork_1.2.0 lubridate_1.9.3
## [21] forcats_1.0.0 stringr_1.5.1 dplyr_1.1.4 purrr_1.0.2 readr_2.1.5
## [26] tidyr_1.3.1 tibble_3.2.1 ggplot2_3.5.1 tidyverse_2.0.0 SCpubr_2.0.2
## [31] Azimuth_0.5.0 shinyBS_0.61.1 Seurat_5.1.0 SeuratObject_5.0.2 sp_2.1-4
## [36] optparse_1.7.5
##
## loaded via a namespace (and not attached):
## [1] R.methodsS3_1.8.2 vroom_1.6.5 poweRlaw_0.80.0 goftest_1.2-3
## [5] DT_0.33 Biostrings_2.72.1 vctrs_0.6.5 spatstat.random_3.3-1
## [9] digest_0.6.37 png_0.1-8 ggrepel_0.9.5 deldir_2.0-4
## [13] parallelly_1.38.0 MASS_7.3-61 Signac_1.14.0 reshape2_1.4.4
## [17] httpuv_1.6.15 qvalue_2.36.0 withr_3.0.1 xfun_0.47
## [21] ggfun_0.1.6 survival_3.7-0 EnsDb.Hsapiens.v86_2.99.0 memoise_2.0.1
## [25] gson_0.1.0 DElegate_1.2.1 tidytree_0.4.6 zoo_1.8-12
## [29] gtools_3.9.5 pbapply_1.7-2 R.oo_1.26.0 KEGGREST_1.44.1
## [33] promises_1.3.0 httr_1.4.7 restfulr_0.0.15 globals_0.16.3
## [37] fitdistrplus_1.2-1 rhdf5filters_1.16.0 rhdf5_2.48.0 rstudioapi_0.16.0
## [41] UCSC.utils_1.0.0 miniUI_0.1.1.1 generics_0.1.3 DOSE_3.30.5
## [45] babelgene_22.9 curl_5.2.2 zlibbioc_1.50.0 ggraph_2.2.1
## [49] polyclip_1.10-7 GenomeInfoDbData_1.2.12 SparseArray_1.4.8 xtable_1.8-4
## [53] pracma_2.4.4 evaluate_0.24.0 S4Arrays_1.4.1 hms_1.1.3
## [57] irlba_2.3.5.1 colorspace_2.1-1 hdf5r_1.3.11 getopt_1.20.4
## [61] ROCR_1.0-11 reticulate_1.38.0 spatstat.data_3.1-2 magrittr_2.0.3
## [65] lmtest_0.9-40 later_1.3.2 viridis_0.6.5 ggtree_3.12.0
## [69] lattice_0.22-6 spatstat.geom_3.3-2 future.apply_1.11.2 shadowtext_0.1.4
## [73] scattermore_1.2 XML_3.99-0.17 cowplot_1.1.3 RcppAnnoy_0.0.22
## [77] pillar_1.9.0 nlme_3.1-166 pwalign_1.0.0 caTools_1.18.2
## [81] compiler_4.4.1 RSpectra_0.16-2 stringi_1.8.4 tensor_1.5
## [85] GenomicAlignments_1.40.0 plyr_1.8.9 crayon_1.5.3 abind_1.4-5
## [89] BiocIO_1.14.0 gridGraphics_0.5-1 googledrive_2.1.1 locfit_1.5-9.10
## [93] graphlayouts_1.1.1 bit_4.0.5 fastmatch_1.1-4 codetools_0.2-20
## [97] crosstalk_1.2.1 bslib_0.8.0 plotly_4.10.4 mime_0.12
## [101] splines_4.4.1 Rcpp_1.0.13 fastDummies_1.7.4 sparseMatrixStats_1.16.0
## [105] cellranger_1.1.0 knitr_1.48 blob_1.2.4 utf8_1.2.4
## [109] seqLogo_1.70.0 AnnotationFilter_1.28.0 fs_1.6.4 listenv_0.9.1
## [113] ggplotify_0.1.2 Matrix_1.7-0 statmod_1.5.0 tzdb_0.4.0
## [117] tweenr_2.0.3 pkgconfig_2.0.3 tools_4.4.1 cachem_1.1.0
## [121] RSQLite_2.3.7 viridisLite_0.4.2 DBI_1.2.3 fastmap_1.2.0
## [125] rmarkdown_2.28 scales_1.3.0 grid_4.4.1 ica_1.0-3
## [129] shinydashboard_0.7.2 Rsamtools_2.20.0 sass_0.4.9 dotCall64_1.1-1
## [133] RANN_2.6.2 farver_2.1.2 scatterpie_0.2.4 tidygraph_1.3.1
## [137] yaml_2.3.10 rtracklayer_1.64.0 cli_3.6.3 leiden_0.4.3.1
## [141] lifecycle_1.0.4 uwot_0.2.2 presto_1.0.0 BSgenome.Hsapiens.UCSC.hg38_1.4.5
## [145] BiocParallel_1.38.0 annotate_1.82.0 timechange_0.3.0 gtable_0.3.5
## [149] rjson_0.2.22 ggridges_0.5.6 progressr_0.14.0 limma_3.60.4
## [153] parallel_4.4.1 ape_5.8 edgeR_4.2.1 jsonlite_1.8.8
## [157] RcppHNSW_0.6.0 TFBSTools_1.42.0 bitops_1.0-8 assertthat_0.2.1
## [161] bit64_4.0.5 Rtsne_0.17 yulab.utils_0.1.7 spatstat.utils_3.1-0
## [165] CNEr_1.40.0 highr_0.11 jquerylib_0.1.4 GOSemSim_2.30.2
## [169] shinyjs_2.1.0 SeuratDisk_0.0.0.9021 spatstat.univar_3.0-0 R.utils_2.12.3
## [173] lazyeval_0.2.2 shiny_1.9.1 htmltools_0.5.8.1 GO.db_3.19.1
## [177] rappdirs_0.3.3 ensembldb_2.28.1 glue_1.7.0 TFMPvalue_0.0.9
## [181] spam_2.10-0 googlesheets4_1.1.1 httr2_1.0.3 XVector_0.44.0
## [185] RCurl_1.98-1.16 rprojroot_2.0.4 treeio_1.28.0 BSgenome_1.72.0
## [189] gridExtra_2.3 JASPAR2020_0.99.10 igraph_2.0.3 R6_2.5.1
## [193] labeling_0.4.3 RcppRoll_0.3.1 GenomicFeatures_1.56.0 cluster_2.1.6
## [197] Rhdf5lib_1.26.0 gargle_1.5.2 aplot_0.2.3 DirichletMultinomial_1.46.0
## [201] DelayedArray_0.30.1 tidyselect_1.2.1 ProtGenerics_1.36.0 ggforce_0.4.2
## [205] future_1.34.0 munsell_0.5.1 KernSmooth_2.23-24 data.table_1.16.0
## [209] htmlwidgets_1.6.4 fgsea_1.30.0 RColorBrewer_1.1-3 rlang_1.1.4
## [213] spatstat.sparse_3.1-0 spatstat.explore_3.3-2 fansi_1.0.6